package qc.module.qms.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.module.platform.dto.dept.DeptSimpleDto;
import qc.module.qms.dto.station.StationDeptDto;
import qc.module.qms.dto.station.StationDeptSetDto;
import qc.module.qms.dto.station.StationDto;
import qc.module.qms.entity.ExchangeCategoryStation;
import qc.module.qms.entity.QmsStation;
import qc.module.qms.entity.QmsStationDept;
import qc.module.qms.mapper.QmsStationMapper;
import qc.module.qms.repository.QmsStationDeptRepository;
import qc.module.qms.repository.QmsStationRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * ExchangeStationService
 *
 * @author QuCheng Tech
 * @since 2024/1/23
 */
@Service
public class QmsStationService {
    private QmsStationRepository repository;

    private ExchangeCategoryStationService categoryStationService;

    private QmsStationDeptRepository categoryDeptRepository;
    
    @Autowired
    private QmsStationDeptService qmsStationDeptService;

    @Autowired
    public void setExchangeStationRepository(QmsStationRepository repository) {
        this.repository = repository;
    }

    @Autowired
    public void setCategoryDeptRepository(ExchangeCategoryStationService categoryStationService) {
        this.categoryStationService = categoryStationService;
    }

    @Autowired
    public void setCategoryDeptRepository(QmsStationDeptRepository categoryDeptRepository) {
        this.categoryDeptRepository = categoryDeptRepository;
    }

    /***
     * 查询所有站点信息
     *
     * @return java.util.List<qc.module.qms.dto.exchangeStation.ExchangeStationDto>
     * @author QuCheng Tech
     * @since 2024/1/25
     */
    public List<StationDto> getAll() {
        LambdaQueryWrapper<QmsStation> wrapper = new LambdaQueryWrapper<>();

        //排序，按站点名称升序
        wrapper.orderByAsc(QmsStation::getStnm);

        //查询数据
        List<QmsStation> ens = repository.selectList(wrapper);
        if (ens != null && ens.size() > 0x0) {
            return QmsStationMapper.MAPPER.toDtoList(ens);
        }

        return null;
    }

    /***
     * 获取指定站点编码集合的站点信息列表
     *
     * @param stationCodes 站点编码集合
     * @return java.util.List<qc.module.qms.dto.exchangeStation.ExchangeStationDto>
     * @author QuCheng Tech
     * @since 2024/1/25
     */
    public List<StationDto> getByFilterStationCodes(String[] stationCodes) {
        //如果传入的站点编码集合为空，返回结果为空
        if (stationCodes != null && stationCodes.length > 0x0) {
            LambdaQueryWrapper<QmsStation> wrapper = new LambdaQueryWrapper<>();

            //根据ID进行筛选
            //优化查询条件：如果站点编码集合只有1个使用eq条件
            if (stationCodes.length == 0x1)
                wrapper.eq(QmsStation::getStcd, stationCodes[0x0]);
            else
                wrapper.in(QmsStation::getStcd, stationCodes);

            //排序，按站点名称升序
            wrapper.orderByAsc(QmsStation::getStnm);

            //查询数据
            List<QmsStation> ens = repository.selectList(wrapper);
            if (ens != null && ens.size() > 0x0) {
                return QmsStationMapper.MAPPER.toDtoList(ens);
            }
        }

        return null;
    }

    /***
     * 查询指定分类ID集合中的站点信息集合
     *
     * @param categoryIds 分类ID集合
     * @return java.util.List<qc.module.qms.dto.exchangeStation.ExchangeStationDto>
     * @author QuCheng Tech
     * @since 2024/1/25
     */
    public List<StationDto> getByCategoryIds(Integer[] categoryIds) {
        //如果传入的分类ID集合为空，返回结果为空
        if (categoryIds != null && categoryIds.length > 0x0) {
            MPJLambdaWrapper<QmsStation> wrapper = new MPJLambdaWrapper<>();
            wrapper.select(QmsStation::getStcd, QmsStation::getStnm);
            wrapper.innerJoin(ExchangeCategoryStation.class, ExchangeCategoryStation::getStcd, QmsStation::getStcd);
            //优化查询条件：如果站分类ID集合只有1个使用eq条件
            if (categoryIds.length == 0x1)
                wrapper.eq(ExchangeCategoryStation::getCid, categoryIds[0x0]);
            else
                wrapper.in(ExchangeCategoryStation::getCid, categoryIds);

            //排序，按站点名称升序
            wrapper.orderByAsc(QmsStation::getStnm);

            //查询数据
            List<QmsStation> ens = repository.selectJoinList(QmsStation.class, wrapper);
            if (ens != null && ens.size() > 0x0) {
                return QmsStationMapper.MAPPER.toDtoList(ens);
            }
        }

        return null;
    }

    /***
     * 查找指定分类ID中的站点信息集合
     *
     * @param categoryId 分类ID 
     * @return java.util.List<qc.module.qms.dto.exchangeStation.ExchangeStationDto>
     * @author QuCheng Tech
     * @since 2024/1/25
     */
    public List<StationDto> getByCategoryId(int categoryId) {
        MPJLambdaWrapper<QmsStation> wrapper = new MPJLambdaWrapper<>();
        wrapper.select(QmsStation::getStcd, QmsStation::getStnm, QmsStation::getParams);
        wrapper.innerJoin(ExchangeCategoryStation.class, ExchangeCategoryStation::getStcd, QmsStation::getStcd);

        wrapper.eq(ExchangeCategoryStation::getCid, categoryId);

        //排序，按站点名称升序
        wrapper.orderByAsc(QmsStation::getStnm);

        //查询数据
        List<QmsStation> ens = repository.selectJoinList(QmsStation.class, wrapper);
        if (ens != null && ens.size() > 0x0) {
            for (QmsStation station : ens) {
                System.out.println("ExchangeStationService getByCategoryId，stcd=" + station.getStcd() + " getParams=" + station.getParams());
            }
            return QmsStationMapper.MAPPER.toDtoList(ens);
        }

        return null;
    }

    /***
     * 获取指定站点信息
     *
     * @param stcd 站点编码
     * @return qc.module.qms.dto.exchangeStation.ExchangeStationDto
     * @author QuCheng Tech
     * @since 2024/1/25
     */
    public StationDto get(String stcd) {
        QmsStation en = repository.selectById(stcd);

        if (en != null)
            return QmsStationMapper.MAPPER.toDto(en);

        return null;
    }

    /**
     * 新增
     *
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String add(StationDto dto) {
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("查询对象不能为空");
        if (StringUtils.isBlank(dto.getStcd())) return QCUnifyReturnValue.Warn("站点编码不能为空");
        if (StringUtils.isBlank(dto.getStnm())) return QCUnifyReturnValue.Warn("站点名称不能为空");

        QmsStation en = QmsStationMapper.MAPPER.toEntity(dto);

        if (repository.insert(en) < 0x1)
            return QCUnifyReturnValue.Warn("新增数据失败");
        return QCUnifyReturnValue.Success();
    }

    /**
     * 修改
     *
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String update(StationDto dto) {
        if (Objects.isNull(dto)) return QCUnifyReturnValue.Warn("查询对象不能为空");
        if (StringUtils.isBlank(dto.getStcd())) return QCUnifyReturnValue.Warn("站点编码不能为空");
        if (StringUtils.isBlank(dto.getStnm())) return QCUnifyReturnValue.Warn("站点名称不能为空");

        if (!isExist(dto.getStcd())) {
            return QCUnifyReturnValue.Warn("修改的站点信息不存在");
        }

        QmsStation en = QmsStationMapper.MAPPER.toEntity(dto);

        repository.updateById(en);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 删除
     *
     * @param stcd 站点编码
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public String delete(String stcd) throws QCPromptException {
        // 1.条件判空
        if (StringUtils.isBlank(stcd))
            throw new QCPromptException("站点编码不能为空");
        
        //2.删除站点与分类关联关系
        categoryStationService.deleteByStcd(stcd);

        //3.删除站点信息
        repository.deleteById(stcd);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 判断站点是否存在
     *
     * @param stcd 站点编码
     * @return 返回true表示存在，false表示不存在
     * @author QuCheng Tech
     * @since 2024/4/16
     */
    public boolean isExist(String stcd) {
        if (Objects.nonNull(repository.selectById(stcd)))
            return true;
        return false;
    }

    /**
     * 根据传入的用户部门ID集合得到有权限的站点编码集合，可以指定站点编码范围
     *
     * @param userDeptIds 用户部门ID集合，不传入时抛出异常提示
     * @param filterStcds 站点编码过滤范围，不传入表示不限制站点编码范围
     * @return java.util.List<java.lang.String>
     * @author QuCheng Tech
     * @since 2024/5/4
     */
    public List<String> getValidStcdsByUserDeptIds(List<Integer> userDeptIds, List<String> filterStcds) throws QCPromptException {
        //查询1次得到所有的站点与部门关联信息，在关联信息中根据传入的部门ID集合进行过滤去重得到站点编码集合
        //如果传入的filterStcds为空，返回去重后的结果；如果不为空取2者的交集
        if (userDeptIds != null && userDeptIds.size() > 0x0) {
            List<QmsStationDept> allStationDepts = categoryDeptRepository.selectList(null);
            if (allStationDepts != null && allStationDepts.size() > 0x0) {
                List<String> result = new ArrayList<>();
                for (QmsStationDept stationDept : allStationDepts) {
                    //传入的用户部门ID集合包含当前关联关系
                    if (userDeptIds.contains(stationDept.getDid())) {
                        //如果传入的站点编码集合不为空，还需要再判断是否在传入的站点编码集合中
                        if (filterStcds != null && filterStcds.size() > 0x0) {
                            if (filterStcds.contains(stationDept.getStcd()))
                                result.add(stationDept.getStcd());
                        } else {
                            //如果未传入站点编码集合，不需要再判断，添加到返回结果中
                            result.add(stationDept.getStcd());
                        }
                    }
                }

                return result;
            } else {
                throw new QCPromptException("系统配置信息错误，系统中不存在任何站点与部门关联信息");
            }
        } else {
            //如果传入的用户部门ID集合为空，抛出异常进行提示
            throw new QCPromptException("根据用户部门得到站点编码集合时必须指定部门ID集合");
        }
    }

    /**
     * 获取站点部门关联集合
     * @param stcds 站点编码集合
     * @return List<StationDeptDto>
     * @throws QCPromptException
     * @author QcCheng Tech
     * @since 2024/5/6
     */
    public List<StationDeptDto> getStationDepts(List<String> stcds, List<DeptSimpleDto> depts) throws QCPromptException {
        if (stcds == null || stcds.size() < 0x1)
            throw new QCPromptException("指定的栏目信息不能为空");
        if (depts == null || depts.size() < 0x1)
            throw new QCPromptException("部门信息不能为空");

        //遍历站点编码，获取每个站点关联的部门取交集
        List<Integer> intersectDeptIds = qmsStationDeptService.getDeptIdsByStcd(stcds.get(0x0));
        for (String stcd : stcds) {
            //如果已取交集的结果为空，不需要再获取后面的栏目关联的部门
            if (intersectDeptIds == null || intersectDeptIds.size() < 0x1)
                break;
            List<Integer> stcdDeptIds = qmsStationDeptService.getDeptIdsByStcd(stcd);
            //如果当前站点获取的关联部门集合为空，不需要取交集和遍历后面的
            if (stcdDeptIds == null || stcdDeptIds.size() < 0x1) {
                intersectDeptIds = null;
                break;
            }
            //取交集
            intersectDeptIds = intersectDeptIds.stream().filter(stcdDeptIds::contains).collect(Collectors.toList());
        }
        List<StationDeptDto> result = new ArrayList<>();
        for (DeptSimpleDto dept : depts) {
            boolean related = false;
            if (intersectDeptIds != null && intersectDeptIds.size() > 0x0) {
                if (intersectDeptIds.contains(dept.getId())) {
                    related = true;
                }
            }
            StationDeptDto dto = new StationDeptDto();
            dto.setDept(dept);
            dto.setChecked(related);
            result.add(dto);
        }

        return result;
    }

    /**
     * 设置站点与部门关联关系，可一次设置多个站点
     *
     * @param dto 站点、部门关联关系
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2024/5/6
     */
    public String setStationDepts(StationDeptSetDto dto) {
        //以站点为基准进行设置，即对传入的所有站点均设置为相同的部门关联关系
        if (dto == null)
            return QCUnifyReturnValue.Warn("设置的信息不能为空");
        if (dto.getStcds() == null || dto.getStcds().size() < 0x1)
            return QCUnifyReturnValue.Warn("设置的站点信息不能为空");

        //遍历站点，先删除站点的关联关系，再添加
        for (String stcd : dto.getStcds()) {
            qmsStationDeptService.deleteDeptsByStcd(stcd);

            if (dto.getDids() != null && dto.getDids().size() > 0x0) {
                for (int did : dto.getDids()) {
                    String addResult = qmsStationDeptService.addStcdDept(stcd, did);
                    if (!StringUtils.isBlank(addResult))
                        return addResult;
                }
            }
        }

        return QCUnifyReturnValue.Success();
    }
}
